/******************* Contiene las variables y funciones globales ****************/
/* Obtengo los parametros de la clase parser.cpp y los asigno a las variables globales
 *
 * [0] = representacion
 * [1] = cantidadDePoblacionesEnGpu
 * [2] = cantidadDePoblacionesEnCpu
 * [3] = tamanioPoblacion
 * [4] = cantidadGenesPorIndividuo
 * [5] = metodoDeSeleccion
 * [6] = operadorCruzamiento
 * [7] = operadorMutacion
 * [8] = mecanismoDeReemplazo
 * [9] = probabilidadCruzamiento
 * [10] = probabilidadMutacion
 * [11] = numeroGeneraciones
 * [12] = gradoNoUniformidad
 * [13] = bloquePorPoblacion
 * [14] = porcentajeElitismo
 * [15] = generacionesMigrar
 * [16] = modoDebug
 * [17] = cantidadIndividuosSeleccionPorRango
 * [18] = inicializacionAutomatica
 * [19] = imprimirPoblacionEntera
 * [20] = inicioRango
 * [21] = finRango
 * [22] = cantHilosBloque
 */

#ifndef GLOBAL_CU
#define GLOBAL_CU

#include "global.cuh"
#include "Parser.h"

//Incluyo la clase cuPrintf para poder imprimir desde GPU
#include "cuPrintf.cu"

/******************* Implementación de Funciones del Device *****************/

__global__ void asignarParametrosDevice(float * parametros){
	cantidadPoblacionesGPUDevice = (int) parametros[1];
	cantidadPoblacionesCPUDevice = (int) parametros[2];
	cantCromosomasPoblacionDevice = (int) parametros[3];
	cantGenesEnCromosomaDevice = (int) parametros[4];
	tipoSeleccionDevice = (int) parametros[5];
	tipoCruzamientoDevice = (int) parametros[6];
	tipoMutacionDevice = (int) parametros[7];
	tipoReemplazoDevice = (int) parametros[8];
	probabilidadCruzamientoDevice = parametros[9];
	probabilidadMutacionDevice = parametros[10];
	numeroGeneracionesDevice = (int) parametros[11];
	gradoNoUniformidadDevice = parametros[12];
	porcentajeElitismoDevice = parametros[14];
	generacionesMigrarDevice = (int) parametros[15];
	cantidadIndividuosSeleccionPorRangoDevice = (int) parametros[17];
	imprimirPoblacionEnteraDevice = (int) parametros[19];
	inicioRangoDevice = parametros[20];
	finRangoDevice = parametros[21];
	cantHilosBloqueDevice = (int) parametros[22];
	totalGenesEnPoblacionDevice = cantCromosomasPoblacionDevice * cantGenesEnCromosomaDevice;
}

__device__ int estaPresente(int valor, int* nuevaPoblacion, int desde, int hasta){
	for(int i = desde; i< hasta; i++){
		if(nuevaPoblacion[i] == valor)
			return 1;
	}
	return 0;
}

__device__ int posicionPrimerLibre(int* poblacionActual, int posicionNuevoCromosoma){
	for(int i=0; i<cantGenesEnCromosomaDevice; i++){
		if(poblacionActual[posicionNuevoCromosoma+i]==-1)
			return i;
	}
	return -1;
}

__device__ int dondeEsta(int* poblacionActual, int valor, int posicionNuevoCromosoma){
	for(int i=0; i<cantGenesEnCromosomaDevice; i++){
		if(poblacionActual[posicionNuevoCromosoma+i]==valor)
			return i;
	}
	return 0;
}

//en lugar de guardar el valor del fitness en el data, tengo que guardar el indice correspondiente al elemento del data anterior para despues hacer el mapeo
__global__ void ordenarDescendente(float *fitnesAOrdenar, int *indicesFitnessOrdenado){
//	cuPrintf("\nOrdenar descendente\n");
	int left = blockIdx.y * cantCromosomasPoblacionDevice;
	int right = left + cantCromosomasPoblacionDevice;
	for(int i = left ; i < right ; i++){
		indicesFitnessOrdenado[i] = i % cantCromosomasPoblacionDevice;
	}
	int aux;
	for(int i = left ; i < right ; i++){
		float max_val = fitnesAOrdenar[i];
		int max_idx = i;
		// Find the bigest value in the range [left, right].
		for(int j = i+1 ; j < right ; j++){
			float val_j = fitnesAOrdenar[j];
			if( val_j > max_val ){
				max_idx = j;
				max_val = val_j;
			}
		}
		// Swap the values.
		if(i != max_idx){
			fitnesAOrdenar[max_idx] = fitnesAOrdenar[i];
			fitnesAOrdenar[i] = max_val;

			aux = indicesFitnessOrdenado[max_idx];
			indicesFitnessOrdenado[max_idx] = indicesFitnessOrdenado[i];
			indicesFitnessOrdenado[i] = aux;
		}
	}
}

__device__ int obtenerNumeroEnRangoEntera(unsigned long valor){
	int resultado;
	if(inicioRangoDevice == finRangoDevice){
		resultado = valor;
	}else{
		int rango = (int)(finRangoDevice - inicioRangoDevice) + 1;
		resultado = (valor % rango) + (int)inicioRangoDevice;
	}
	return resultado;
}

__device__ float obtenerNumeroEnRangoReal(float valor){
	float resultado;
	if(inicioRangoDevice == finRangoDevice){
		resultado = valor;
	}else{
		float media = (finRangoDevice - inicioRangoDevice) / 2;
		resultado = valor * media + (inicioRangoDevice + finRangoDevice) / 2;
	}
	return resultado;
}
/******************* Implementacion de Funciones del host *****************/

int estaPresenteCPU(int valor, int* nuevaPoblacion, int desde, int hasta){
	for(int i = desde; i< hasta; i++){
		if(nuevaPoblacion[i] == valor)
			return 1;
	}
	return 0;
}

int posicionPrimerLibreCPU(int* poblacionActual, int posicionNuevoCromosoma){
	for(int i=0; i<cantGenesEnCromosoma; i++){
		if(poblacionActual[posicionNuevoCromosoma+i]==-1)
			return i;
	}
	return -1;
}

int dondeEstaCPU(int* poblacionActual, int valor, int posicionNuevoCromosoma){
	for(int i=0; i<cantGenesEnCromosoma; i++){
		if(poblacionActual[posicionNuevoCromosoma+i]==valor)
			return i;
	}
	return 0;
}

float * asignarParametros(Parser parser){
	float * parametros = (float *) malloc(sizeof(float) * cantidadParametros);
	tipoRepresentacion = parser.getValueOfKey<int>("representacion");
	parametros[0] = tipoRepresentacion;
	cantidadPoblacionesGPU = parser.getValueOfKey<int>("cantidadDePoblacionesEnGpu");
	parametros[1] = cantidadPoblacionesGPU;
	cantidadPoblacionesCPU = parser.getValueOfKey<int>("cantidadDePoblacionesEnCpu");
	parametros[2] = cantidadPoblacionesCPU;
	cantCromosomasPoblacion = parser.getValueOfKey<int>("tamanioPoblacion");
	parametros[3] = cantCromosomasPoblacion;
	cantGenesEnCromosoma = parser.getValueOfKey<int>("cantidadGenesPorIndividuo");
	parametros[4] = cantGenesEnCromosoma;
	tipoSeleccion = parser.getValueOfKey<int>("metodoDeSeleccion");
	parametros[5] = tipoSeleccion;
	tipoCruzamiento = parser.getValueOfKey<int>("operadorCruzamiento");
	parametros[6] = tipoCruzamiento;
	tipoMutacion = parser.getValueOfKey<int>("operadorMutacion");
	parametros[7] = tipoMutacion;
	tipoReemplazo = parser.getValueOfKey<int>("mecanismoDeReemplazo");
	parametros[8] = tipoReemplazo;
	probabilidadCruzamiento = parser.getValueOfKey<float>("probabilidadCruzamiento");
	parametros[9] = probabilidadCruzamiento;
	probabilidadMutacion = parser.getValueOfKey<float>("probabilidadMutacion");
	parametros[10] = probabilidadMutacion;
	numeroGeneraciones = parser.getValueOfKey<int>("numeroGeneraciones");
	parametros[11] = numeroGeneraciones;
	gradoNoUniformidad = parser.getValueOfKey<float>("gradoNoUniformidad");
	parametros[12] = gradoNoUniformidad;
	bloquePorPoblacion = parser.getValueOfKey<int>("bloquePorPoblacion");
	parametros[13] = bloquePorPoblacion;
	porcentajeElitismo = parser.getValueOfKey<float>("porcentajeElitismo");
	parametros[14] = porcentajeElitismo;
	generacionesMigrar = parser.getValueOfKey<int>("generacionesMigrar");
	parametros[15] = generacionesMigrar;
	modoDebug = parser.getValueOfKey<int>("modoDebug");
	parametros[16] = modoDebug;
	cantidadIndividuosSeleccionPorRango = parser.getValueOfKey<int>("cantidadIndividuosSeleccionPorRango");
	parametros[17] = cantidadIndividuosSeleccionPorRango;
	inicializacionAutomatica = parser.getValueOfKey<int>("inicializacionAutomatica");
	parametros[18] = inicializacionAutomatica;
	imprimirPoblacionEntera = parser.getValueOfKey<int>("imprimirPoblacionEntera");
	parametros[19] = imprimirPoblacionEntera;
	inicioRango = parser.getValueOfKey<float>("inicioRango");
	parametros[20] = inicioRango;
	finRango = parser.getValueOfKey<float>("finRango");
	parametros[21] = finRango;
	cantHilosBloque = parser.getValueOfKey<int>("cantHilosBloque");
	parametros[22] = cantHilosBloque;
	totalGenesEnPoblacion = cantCromosomasPoblacion * cantGenesEnCromosoma;
	return parametros;
}

//en lugar de guardar el valor del fitness en el data, tengo que guardar el indice correspondiente al elemento del data anterior para despues hacer el mapeo
void ordenarDescendenteCPU(float *fitnesAOrdenar, int *indicesFitnessOrdenado, int nroPoblacion){
	int left = nroPoblacion * cantCromosomasPoblacion;
	int right = left + cantCromosomasPoblacion;
	for(int i = left ; i < right ; i++){
		indicesFitnessOrdenado[i] = i % cantCromosomasPoblacion;
	}
	int aux;
	for(int i = left; i < right ; i++){
		float max_val = fitnesAOrdenar[i];
		int max_idx = i;
		// Find the bigest value in the range [left, right].
		for(int j = i+1 ; j < right ; j++){
			float val_j = fitnesAOrdenar[j];
			if( val_j > max_val ){
				max_idx = j;
				max_val = val_j;
			}
		}
		// Swap the values.
		if(i != max_idx){
			fitnesAOrdenar[max_idx] = fitnesAOrdenar[i];
			fitnesAOrdenar[i] = max_val;
			aux = indicesFitnessOrdenado[max_idx];
			indicesFitnessOrdenado[max_idx] = indicesFitnessOrdenado[i];
			indicesFitnessOrdenado[i] = aux;
		}
	}
}

void generarNumerosAleatoriosBinaria(MersenneTwister *mt, unsigned long* numerosAleatoriosInicializacion, unsigned long* numerosAleatoriosSeleccion, unsigned long* numerosAleatoriosCruzamiento, unsigned long* numerosAleatoriosMutacion, unsigned long* numerosAleatoriosProbabilidadCruzamiento, unsigned long* numerosAleatoriosProbabilidadMutacion){
	int tamVectorIni = totalGenesGPU + totalGenesCPU;
	int tamVectorSel;
	int contador = 0;
	if(tipoSeleccion == 1){
		tamVectorSel = (totalIndividuosCPU + totalIndividuosGPU)*2;
	}else{
		tamVectorSel = totalIndividuosCPU + totalIndividuosGPU;
	}
	int tamVectorCruz;
	int tamVectorPCruz;
	//Si el cruzamiento es por 1 punto la cantidad de nros aleatorios es igual al nro de individuos/2
	if(tipoCruzamiento == 0){
		tamVectorCruz = (totalIndividuosCPU + totalIndividuosGPU)/2;
		tamVectorPCruz = (totalIndividuosCPU + totalIndividuosGPU)/2;
	}else{
		//Si el cruzamiento es por 2 puntos la cantidad de nros aleatorios es igual al nro de individuos
		if(tipoCruzamiento == 1){
			tamVectorCruz = totalIndividuosCPU + totalIndividuosGPU;
			tamVectorPCruz = (totalIndividuosCPU + totalIndividuosGPU)/2;
		}else{ //Si es uniforme no se usa este arreglo, solo se usa el de probabilidadCruzamiento
			tamVectorCruz = 0;
			tamVectorPCruz = (totalIndividuosCPU + totalIndividuosGPU)*cantGenesEnCromosoma/2;
		}
	}
	int tamVectorMut = totalIndividuosCPU + totalIndividuosGPU;
	int tamVectorPMut = totalIndividuosCPU + totalIndividuosGPU;

	//printf("\n**** Nros Aleatorios Inicializacion \n ");
	//printf("\nn tamVectorIni = %d \n ", tamVectorIni);
	for(int i = 0; i < tamVectorIni; i++){
		contador++;
		numerosAleatoriosInicializacion[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosInicializacion[i]);
	}
	//printf("\n ");
	//printf("\n\n <<<<<<<<<<<<<<<<<<CONTADOR = %d >>>>>>>>>>>>>>>>>>>\n\n ", contador);
	//printf("\n**** Nros Aleatorios Seleccion \n ");
	//printf("\nn tamVectorSel = %d \n ", tamVectorSel);
	for(int i = 0; i < tamVectorSel ; i++){
		contador++;
		numerosAleatoriosSeleccion[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosSeleccion[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Cruzamiento \n ");
	//printf("\nn tamVectorCruz = %d \n ", tamVectorCruz);
	for(int i = 0; i<tamVectorCruz; i++){
		contador++;
		numerosAleatoriosCruzamiento[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosCruzamiento[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Mutacion \n ");
	//printf("\nn tamVectorMut = %d \n ", tamVectorMut);
	for(int i = 0; i<tamVectorMut; i++){
		contador++;
		numerosAleatoriosMutacion[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosMutacion[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Prob Cruzamiento \n ");
	//printf("\nn tamVectorPCruz = %d \n ", tamVectorPCruz);
	for(int i = 0; i<tamVectorPCruz; i++){
		contador++;
		numerosAleatoriosProbabilidadCruzamiento[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosProbabilidadCruzamiento[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Prob Mutacion \n ");
	//printf("\nn tamVectorPMut = %d \n ", tamVectorPMut);
	for(int i = 0; i<tamVectorPMut; i++){
		contador++;
		numerosAleatoriosProbabilidadMutacion[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosProbabilidadMutacion[i]);
	}
	//printf("\n ");
	//printf("\n\n <<<<<<<<<<<<<<<<<<CONTADOR = %d >>>>>>>>>>>>>>>>>>>\n\n ", contador);
}

void generarNumerosAleatoriosEntera(MersenneTwister *mt, unsigned long* numerosAleatoriosInicializacion, unsigned long* numerosAleatoriosSeleccion, unsigned long* numerosAleatoriosCruzamiento, unsigned long* numerosAleatoriosMutacion, unsigned long* numerosAleatoriosProbabilidadCruzamiento, unsigned long* numerosAleatoriosProbabilidadMutacion){
	int tamVectorIni = totalGenesGPU + totalGenesCPU;
	int tamVectorSel;
	int contador = 0;
	if(tipoSeleccion == 1){
		tamVectorSel = (totalIndividuosCPU + totalIndividuosGPU)*2;
	}else{
		tamVectorSel = totalIndividuosCPU + totalIndividuosGPU;
	}
	int tamVectorCruz;
	int tamVectorPCruz;
	//Si el cruzamiento es por 1 punto la cantidad de nros aleatorios es igual al nro de individuos/2
	if(tipoCruzamiento == 0){
		tamVectorCruz = (totalIndividuosCPU + totalIndividuosGPU)/2;
		tamVectorPCruz = (totalIndividuosCPU + totalIndividuosGPU)/2;
	}else{
		//Si el cruzamiento es por 2 puntos la cantidad de nros aleatorios es igual al nro de individuos
		if(tipoCruzamiento == 1){
			tamVectorCruz = totalIndividuosCPU + totalIndividuosGPU;
			tamVectorPCruz = (totalIndividuosCPU + totalIndividuosGPU)/2;
		}else{ //Si es uniforme no se usa este arreglo, solo se usa el de probabilidadCruzamiento
			tamVectorCruz = 0;
			tamVectorPCruz = (totalIndividuosCPU + totalIndividuosGPU)*cantGenesEnCromosoma/2;
		}
	}

	int tamVectorMut;
	int tamVectorPMut;
	if(tipoMutacion == 0){
		tamVectorMut = (totalIndividuosCPU + totalIndividuosGPU)*2;
		tamVectorPMut = totalIndividuosCPU + totalIndividuosGPU;
	}else{
		tamVectorMut = (totalIndividuosCPU + totalIndividuosGPU)*cantGenesEnCromosoma;
		tamVectorPMut = (totalIndividuosCPU + totalIndividuosGPU)*cantGenesEnCromosoma;
	}

	//printf("\n**** Nros Aleatorios Inicializacion \n ");
	//printf("\nn tamVectorIni = %d \n ", tamVectorIni);
	for(int i = 0; i < tamVectorIni; i++){
		contador++;
		numerosAleatoriosInicializacion[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosInicializacion[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Seleccion \n ");
	//printf("\nn tamVectorSel = %d \n ", tamVectorSel);
	for(int i = 0; i < tamVectorSel ; i++){
		contador++;
		numerosAleatoriosSeleccion[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosSeleccion[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Cruzamiento \n ");
	//printf("\nn tamVectorCruz = %d \n ", tamVectorCruz);
	for(int i = 0; i<tamVectorCruz; i++){
		contador++;
		numerosAleatoriosCruzamiento[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosCruzamiento[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Mutacion \n ");
	//printf("\nn tamVectorMut = %d \n ", tamVectorMut);
	for(int i = 0; i<tamVectorMut; i++){
		contador++;
		numerosAleatoriosMutacion[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosMutacion[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Prob Cruzamiento \n ");
	//printf("\nn tamVectorPCruz = %d \n ", tamVectorPCruz);
	for(int i = 0; i<tamVectorPCruz; i++){
		contador++;
		numerosAleatoriosProbabilidadCruzamiento[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosProbabilidadCruzamiento[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Prob Mutacion \n ");
	//printf("\nn tamVectorPMut = %d \n ", tamVectorPMut);
	contador = 0;
	for(int i = 0; i<tamVectorPMut; i++){
		contador++;
		numerosAleatoriosProbabilidadMutacion[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosProbabilidadMutacion[i]);
	}
	printf("\n ");
	printf("\n\n <<<<<<<<<<<<<<<<<<CONTADOR tamVectorPMut = %d >>>>>>>>>>>>>>>>>>>\n\n ", contador);
}

void generarNumerosAleatoriosPermutacion(MersenneTwister *mt, unsigned long* numerosAleatoriosInicializacion, unsigned long* numerosAleatoriosSeleccion, unsigned long* numerosAleatoriosCruzamiento, unsigned long* numerosAleatoriosMutacion, unsigned long* numerosAleatoriosProbabilidadCruzamiento, unsigned long* numerosAleatoriosProbabilidadMutacion){
	int tamVectorIni = totalGenesGPU + totalGenesCPU;
	int tamVectorSel;
	int contador = 0;
	if(tipoSeleccion == 1){
		tamVectorSel = (totalIndividuosCPU + totalIndividuosGPU)*2;
	}else{
		tamVectorSel = totalIndividuosCPU + totalIndividuosGPU;
	}
	int tamVectorCruz;

	//Si el cruzamiento es PMX la cantidad de nros aleatorios es igual al nro de individuos
	if(tipoCruzamiento == 0){
		tamVectorCruz = totalIndividuosCPU + totalIndividuosGPU;
	}else{
		//Si el cruzamiento es OX la cantidad de nros aleatorios es igual al nro de individuos
		if(tipoCruzamiento == 1){
			tamVectorCruz = totalIndividuosCPU + totalIndividuosGPU;
		}else{ //Si es uniforme no se usa este arreglo, solo se usa el de probabilidadCruzamiento
			tamVectorCruz = 0;
		}
	}
	int tamVectorPCruz = (totalIndividuosCPU + totalIndividuosGPU)/2;
	int tamVectorMut = (totalIndividuosCPU + totalIndividuosGPU)*2;
	int tamVectorPMut = totalIndividuosCPU + totalIndividuosGPU;

	//printf("\n**** Nros Aleatorios Inicializacion \n ");
	//printf("\nn tamVectorIni = %d \n ", tamVectorIni);
	for(int i = 0; i < tamVectorIni; i++){
		contador++;
		numerosAleatoriosInicializacion[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosInicializacion[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Seleccion \n ");
	//printf("\nn tamVectorSel = %d \n ", tamVectorSel);
	for(int i = 0; i < tamVectorSel ; i++){
		contador++;
		numerosAleatoriosSeleccion[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosSeleccion[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Cruzamiento \n ");
	//printf("\nn tamVectorCruz = %d \n ", tamVectorCruz);
	for(int i = 0; i<tamVectorCruz; i++){
		contador++;
		numerosAleatoriosCruzamiento[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosCruzamiento[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Mutacion \n ");
	//printf("\nn tamVectorMut = %d \n ", tamVectorMut);
	for(int i = 0; i<tamVectorMut; i++){
		contador++;
		numerosAleatoriosMutacion[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosMutacion[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Prob Cruzamiento \n ");
	//printf("\nn tamVectorPCruz = %d \n ", tamVectorPCruz);
	for(int i = 0; i<tamVectorPCruz; i++){
		contador++;
		numerosAleatoriosProbabilidadCruzamiento[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosProbabilidadCruzamiento[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Prob Mutacion \n ");
	//printf("\nn tamVectorPMut = %d \n ", tamVectorPMut);
	for(int i = 0; i<tamVectorPMut; i++){
		contador++;
		numerosAleatoriosProbabilidadMutacion[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosProbabilidadMutacion[i]);
	}
	//printf("\n ");
	//printf("\n\n <<<<<<<<<<<<<<<<<<CONTADOR = %d >>>>>>>>>>>>>>>>>>>\n\n ", contador);
}

void generarNumerosAleatoriosReal(MersenneTwister *mt, float* numerosAleatoriosInicializacion, unsigned long* numerosAleatoriosSeleccion, unsigned long* numerosAleatoriosCruzamiento, unsigned long* numerosAleatoriosMutacion, unsigned long* numerosAleatoriosProbabilidadCruzamiento, unsigned long* numerosAleatoriosProbabilidadMutacion){
	int tamVectorIni = totalGenesGPU + totalGenesCPU;
	int tamVectorSel;
	int contador = 0;
	if(tipoSeleccion == 1){
		tamVectorSel = (totalIndividuosCPU + totalIndividuosGPU)*2;
	}else{
		tamVectorSel = totalIndividuosCPU + totalIndividuosGPU;
	}
	int tamVectorCruz;
	int tamVectorPCruz;

	//Si el cruzamiento es aritmético la cantidad de nros aleatorios es igual al nro de individuos/2
	if(tipoCruzamiento == 0){
		tamVectorCruz = totalIndividuosCPU + totalIndividuosGPU;
		tamVectorPCruz = (totalIndividuosCPU + totalIndividuosGPU)/2;
	}else{
		if(tipoCruzamiento == 1){
			tamVectorCruz = totalIndividuosCPU + totalIndividuosGPU;
			tamVectorPCruz = (totalIndividuosCPU + totalIndividuosGPU)/2;
		}else{
			tamVectorCruz = (totalIndividuosCPU + totalIndividuosGPU)/2;
			tamVectorPCruz = (totalIndividuosCPU + totalIndividuosGPU)/2;
		}
	}
	int tamVectorMut;
	if(tipoMutacion == 0){
		tamVectorMut = (totalIndividuosCPU + totalIndividuosGPU)*2;
	}else{
		tamVectorMut = (totalIndividuosCPU + totalIndividuosGPU)*3;
	}
	int tamVectorPMut = (totalIndividuosCPU + totalIndividuosGPU);

	//printf("\n**** Nros Aleatorios Inicializacion \n ");
	//printf("\nn tamVectorIni = %d \n ", tamVectorIni);
	for(int i = 0; i < tamVectorIni; i++){
		contador++;
		numerosAleatoriosInicializacion[i] = mt->genrand_real();
		//printf("%f ", numerosAleatoriosInicializacion[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Seleccion \n ");
	//printf("\nn tamVectorSel = %d \n ", tamVectorSel);
	for(int i = 0; i < tamVectorSel ; i++){
		contador++;
		numerosAleatoriosSeleccion[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosSeleccion[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Cruzamiento \n ");
	//printf("\nn tamVectorCruz = %d \n ", tamVectorCruz);
	for(int i = 0; i<tamVectorCruz; i++){
		contador++;
		numerosAleatoriosCruzamiento[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosCruzamiento[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Mutacion \n ");
	//printf("\nn tamVectorMut = %d \n ", tamVectorMut);
	for(int i = 0; i<tamVectorMut; i++){
		contador++;
		numerosAleatoriosMutacion[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosMutacion[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Prob Cruzamiento \n ");
	//printf("\nn tamVectorPCruz = %d \n ", tamVectorPCruz);
	for(int i = 0; i<tamVectorPCruz; i++){
		contador++;
		numerosAleatoriosProbabilidadCruzamiento[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosProbabilidadCruzamiento[i]);
	}
	//printf("\n ");
	//printf("\n**** Nros Aleatorios Prob Mutacion \n ");
	//printf("\nn tamVectorPMut = %d \n ", tamVectorPMut);
	for(int i = 0; i<tamVectorPMut; i++){
		contador++;
		numerosAleatoriosProbabilidadMutacion[i] = mt->genrand_int32();
		//printf("%10.8lu ", numerosAleatoriosProbabilidadMutacion[i]);
	}
	//printf("\n ");
	//printf("\n\n <<<<<<<<<<<<<<<<<<CONTADOR = %d >>>>>>>>>>>>>>>>>>>\n\n ", contador);
}

int obtenerNumeroEnRangoEnteraCPU(unsigned long valor){
	int resultado;
	if(inicioRango == finRango){
		resultado = valor;
	}else{
		int rango = (int)(finRango - inicioRango) + 1;
		resultado = (valor % rango) + (int)inicioRango;
	}
	return resultado;
}

float obtenerNumeroEnRangoRealCPU(float valor){
	float resultado;
	if(inicioRango == finRango){
		resultado = valor;
	}else{
		float media = (finRango - inicioRango) / 2;
		resultado = valor * media + (inicioRango + finRango) / 2;
	}
	return resultado;
}

#endif
